/**
 * 
 */
package edu.umd.clip.lm.playground;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.util.HashMap;

import edu.umd.clip.lm.util.*;

/**
 * @author Denis Filimonov <den@cs.umd.edu>
 *
 */
public class Memtest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
        final MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
		MemoryUsage memuse1 = memoryBean.getHeapMemoryUsage();
		MemoryUsage memuse2 = memoryBean.getHeapMemoryUsage();
		MemoryUsage memuse3 = memoryBean.getHeapMemoryUsage();
		MemoryUsage memuse4 = memoryBean.getHeapMemoryUsage();
		MemoryUsage memuse5 = memoryBean.getHeapMemoryUsage();
		MemoryUsage memuse6 = memoryBean.getHeapMemoryUsage();
		
		final int size = 1000000;
		
		System.gc();
		memuse1 = memoryBean.getHeapMemoryUsage();
		Object[] array1 = new Object[size];
		for(int i=0; i<size; ++i) {
			array1[i] = new Object();
		}
		System.gc();
		memuse2 = memoryBean.getHeapMemoryUsage();
		
		Long[] array2 = new Long[size];
		for(int i=0; i<size; ++i) {
			array2[i] = new Long(i);
		}
		System.gc();
		memuse3 = memoryBean.getHeapMemoryUsage();
		
		HashMap<Long,Object> hash1 = new HashMap<Long,Object>(size);
		for(int i=0; i<size; ++i) {
			hash1.put(array2[i], array1[i]);
		}
		System.gc();
		memuse4 = memoryBean.getHeapMemoryUsage();
		
		HashMap<Long,Integer> hash2 = new HashMap<Long,Integer>(size);
		for(int i=0; i<size; ++i) {
			hash2.put(new Long(i), new Integer(i));
		}
		System.gc();
		memuse5 = memoryBean.getHeapMemoryUsage();
		
		Long2IntMap hash3 = new Long2IntMap(size);
		for(int i=0; i<size; ++i) {
			hash3.put(i, i);
		}
		System.gc();
		memuse6 = memoryBean.getHeapMemoryUsage();
		
		System.out.printf("Object array: %f bytes per element\n", (float)(memuse2.getUsed() - memuse1.getUsed()) / size);
		System.out.printf("Long array: %f bytes per element\n", (float)(memuse3.getUsed() - memuse2.getUsed()) / size);
		System.out.printf("Hash table: %f bytes per element\n", (float)(memuse4.getUsed() - memuse3.getUsed()) / size);
		System.out.printf("Std Hash table: %f bytes per element\n", (float)(memuse5.getUsed() - memuse4.getUsed()) / size);
		System.out.printf("Long2Int Hash table: %f bytes per element\n", (float)(memuse6.getUsed() - memuse5.getUsed()) / size);
		
		// prevent dead variable removal optimization
		touch(array1, args);
		touch(array2, args);
		touch(hash1, args);
		touch(hash2, args);
		touch(hash3, args);
	}

	public static void touch(Object o1, Object o2) {
		if (o1.equals(o2)) {
			System.out.println();
		}
	}
}
